home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 2088 < prev    next >
Encoding:
Text File  |  1996-08-06  |  7.5 KB  |  257 lines

  1. Path: gatorbox_srqa_121.arh.cdc.com!user
  2. From: whatmuff@cdc.com (Dave Whatmuff)
  3. Newsgroups: comp.lang.c++,comp.lang.fortran
  4. Subject: Re: Calling Fortran in C++
  5. Date: Mon, 15 Jan 1996 12:22:58 -0600
  6. Organization: Control Data Systems, Inc.
  7. Message-ID: <whatmuff-1501961222580001@gatorbox_srqa_121.arh.cdc.com>
  8. References: <4cr87l$794$1@mhafc.production.compuserve.com>
  9. NNTP-Posting-Host: 129.179.62.121
  10.  
  11. In article <4cr87l$794$1@mhafc.production.compuserve.com>, Steve Harris
  12. <100016.2166@CompuServe.COM> wrote:
  13.  
  14. > Hello,
  15. > Can anyone  provide me with a 'simple' example, with source code 
  16. > and an 'idiots' step guide, on how to call some FORTRAN code from 
  17. > MS VISUAL C++.
  18. .....snip.....
  19.  
  20. Hi Steve,
  21. I'm in the process of porting a Unix engineering graphics application to
  22. WindowsNT.
  23. The code is about 100,000 lines long split 50/50 Fortran/C.
  24.  
  25. Most of last week I spent trying to understand the documentation on the
  26. subject of mixed language programming, and in the process, wrote a test
  27. example which covered most of what I required.
  28.  
  29. My example has a Fortran main, whilst your question suggested that you
  30. needed a C main, but I do make calls in both directions, so this might be
  31. useful to you. As far as compilation and link is concerned, I simply
  32. created .obj files from the C code, using the Visual C++ compiler, and
  33. then included those files when building the "project" under Fortran
  34. Powerstation.
  35.  
  36. For my own interest, and future reference, I wrote a small document
  37. describing the process, which I include here.
  38.  
  39. Good luck,
  40. Dave
  41.  
  42. Notes on Mixed-language programming in WindowsNT
  43. ------------------------------------------------
  44.  
  45. Using Fortran Powerstation 4.0 and Visual C++ 2.0
  46.  
  47. Basic premise is to leave the same as much of the existing code as
  48. possible, and write whatever extra stuff is necessary to cross-talk. This
  49. is because any C code called from Fortran, is also called from C (and
  50. vice-versa) so any changes to existing code would have ripple effect. In
  51. other words, if FORTRAN calls a C function also called by C, I prefer to
  52. change the FORTRAN calls rather that the C called, and the same for C
  53. calling FORTRAN.
  54.  
  55. C calling FORTRAN
  56. -----------------
  57.  
  58. 1. Use __stdcall parameter in prototype declaration for all FORTRAN
  59. routines called, to define FORTRAN calling and cleanup protocol.
  60.  
  61. 2. Names should be uppercase.
  62.  
  63. 3. All args should be pointers, and any string arguments should be
  64. followed by an unsigned int giving the length of the string (best if last
  65. arg, but I understand that string args should always be immediately
  66. followed by the "hidden" length, even if in middle of arg list).
  67.  
  68. 4. Structures duplicating named COMMON blocks are pretty much standard but
  69. struct names should be in uppercase like the COMMON name. Also beware of
  70. different storage rules - may need -
  71.  
  72. #pragma pack(2)
  73. struct {..........} NAME;
  74. #pragma pack()
  75.  
  76. to ensure even byte storage.
  77.  
  78. 5. FORTRAN functions return values as standard -- I haven't tried
  79. returning a string value, but integer and real functions are OK.
  80.  
  81. FORTRAN calling C
  82. -----------------
  83.  
  84. 1. All args in C functions called from FORTRAN should be pointers. (This
  85. is the same in Unix, so any C functions called from Fortran already had
  86. pointer arguments)
  87.  
  88. 2. Use INTERFACE block in program block which makes the call, to define -
  89.  
  90.    C calling and cleanup protocol
  91.    all arguments as REFERENCE (actually only necessary for strings to
  92. prevent Fortran adding the "hidden" length argument, but makes rest
  93. specific)
  94.    ALIAS to allow C function names to remain same
  95.  
  96.    see example program following -
  97.  
  98.  Example FORTRAN source -
  99. -------------------------
  100.  
  101.       PROGRAM MIXLANG
  102.  
  103.       INTERFACE
  104.               INTEGER FUNCTION CFUNC(I,F,C)
  105.               !MS$ATTRIBUTES C, ALIAS:'_cfunc_' :: CFUNC
  106.               !MS$ATTRIBUTES REFERENCE :: I
  107.               !MS$ATTRIBUTES REFERENCE :: F
  108.               !MS$ATTRIBUTES REFERENCE :: C
  109.               INTEGER I
  110.               REAL F
  111.               CHARACTER*10 C
  112.               END FUNCTION CFUNC
  113.       END INTERFACE
  114. *
  115.       CHARACTER C*10
  116.       COMMON/MIXCOM/I,F,C
  117.       PRINT *,'Test of mixed language programming'
  118.       PRINT *,'Setting COMMON values'
  119.       I=98
  120.       F=3.14159
  121.       C="TEST text\0"C
  122.       PRINT *,' I=',I,' F=',F,' C=',C
  123.       K=CFUNC(I,F,C)
  124.       PRINT *,'Return value from CFUNC=',K
  125.       STOP
  126.       END
  127. *
  128.       SUBROUTINE FSUB(I1,F1,C1)
  129.       CHARACTER C1*(*), C*10
  130.       COMMON/MIXCOM/I,F,C
  131.       L=LEN(C1)
  132.       PRINT *,'FSUB argument values'
  133.       PRINT *,' I1=',I1,' F1=',F1,' C1=',C1,' L=',L
  134.       RETURN
  135.       END
  136. *
  137.       FUNCTION FFUNC(I,F,C)
  138.       CHARACTER C*(*)
  139.       L=LEN(C)
  140.       PRINT *,'FFUNC argument values'
  141.       PRINT *,' I=',I,' F=',F,' C=',C,' L=',L
  142.       FFUNC=F
  143.       RETURN
  144.       END
  145. *
  146.       FUNCTION IFUNC(I,F,C)
  147.       CHARACTER C*10
  148.       PRINT *,'IFUNC argument values'
  149.       PRINT *,' I=',I,' F=',F,' C=',C
  150.       IFUNC=I
  151.       RETURN
  152.       END
  153.  
  154.  Example C source -
  155. -------------------
  156.  
  157. #include <stdio.h>
  158. #include <string.h>
  159.  
  160. extern struct {int i; float f; char c[10];} MIXCOM;
  161. extern void __stdcall FSUB(int*,float*,char*,int);
  162. extern double __stdcall FFUNC(int*,float*,char*,int);
  163. extern int __stdcall IFUNC(int*,float*,char*,int);
  164.  
  165. cfunc_(i2,f2,c2)
  166. int *i2;
  167. float *f2;
  168. char *c2;
  169. {
  170.   int i3;
  171.   float f3;
  172.   char *c3;
  173.   int len;
  174.  
  175.   i3= *i2;
  176.   f3= *f2;
  177.   c3= c2;
  178.  
  179.   len=strlen(c2)+1;
  180.  
  181.   printf("cfunc arguments - i2=%d f2=%f c2=%s len=%d\n",*i2,*f2,c2,len);
  182.  
  183.   printf("i3=%d\n",i3);
  184.   printf("f3=%f\n",f3);
  185.   printf("c3=%s\n",c3);
  186.  
  187.  
  188.   printf("struct values i=%d f=%f c=%s\n",MIXCOM.i,MIXCOM.f,MIXCOM.c);
  189.  
  190.   fflush(stdout);
  191.  
  192.   FSUB(&i3,&f3,c3,len);
  193.     fflush(stdout);
  194.  
  195.   printf("Return value from ffunc=%f\n",FFUNC(&i3,&f3,c3,len));
  196.     fflush(stdout);
  197.  
  198.   printf("Return value from ifunc=%d\n",IFUNC(&i3,&f3,c3,len));
  199.     fflush(stdout);
  200.  
  201.   return(i3);
  202.  
  203. }
  204.  
  205.  Program output -
  206. ------------------
  207.  
  208. Test of mixed language programming
  209. Setting COMMON values
  210.  I=         98 F=       3.141590 C=TEST textcfunc arguments - i2=98 f2=3.141590
  211. c2=TEST text len=10
  212. i3=98
  213. f3=3.141590
  214. c3=TEST text
  215. struct values i=98 f=3.141590 c=TEST text
  216.  
  217. FSUB argument values
  218.  I1=    98 F1=  3.141590 C1=TEST text L=    10
  219. FFUNC argument values
  220.  I=    98 F=  3.141590 C=TEST text L=    10Return value from ffunc=3.141590
  221.  
  222. IFUNC argument values
  223.  I=    98 F=  3.141590 C=TEST textReturn value from ifunc=98
  224.  
  225. Return value from CFUNC=    98
  226. Stop - Program terminated.
  227.  
  228. Notes -
  229. -------
  230.  
  231. A couple of interesting things about this ouput -
  232. 1. When I ran the program initially (without the fflush statements in the
  233. C code), I got the output shown above, but when I redirected the output to
  234. a file to add to this document, the Fortran output came out all together,
  235. followed by the C output, suggesting that different buffer files are used
  236. for the two. However, when I added the fflush statements, the redirected
  237. file came out as above. 
  238.  
  239. 2. Note the LF/CR positioning between output from the two languages -
  240.    Fortran/C has no included LF/CR 
  241.    Fortran/Fortran is OK, as is C/C
  242.    but C/Fortran has two
  243.  
  244. This might suggest that PRINT * sends a preceding LF/CR but no succeeding,
  245. whilst printf() does the reverse (??)
  246.  
  247. ==============================================================================
  248.  
  249. -- 
  250. +-------------------------------------------------------------------+
  251. |  Dave Whatmuff                |  Voice:     +1 612 482 4974       |
  252. |  Control Data Systems, Inc.   |                                   |
  253. |  Mail Station: ARH236         |  FAX:       +1 612 482 4985       |
  254. |  4201 Lexington Avenue North  |                                   |
  255. |  Arden Hills, MN  55126  USA  |  Internet: whatmuff@cdc.com       |
  256. +-------------------------------------------------------------------+
  257.